
#![allow(dead_code)]

use std::io;
use std::cmp::Ordering;
use rand::prelude::*;
// use rand::Rng;
fn main() {
    // test_io();

    // test_pattern();

    // test_rand();

    // test_panics();
    
    test_game();
}

// 生成随机数，范围0-100
// 使用rand crate， https://crates.io/crates/rand
// https://rust-random.github.io/book/guide-start.html
fn test_rand(){
    // We can use random() immediately. It can produce values of many common types:
    let num: u8 = random();
    println!("num is {}", num);
    if random() { // generates a boolean
        println!("Heads!");
    }

    // If we want to be a bit more explicit (and a little more efficient) we can
    // make a handle to the thread-local generator:
    let mut rng = thread_rng();
    if rng.gen() { // random bool
        let x: f64 = rng.gen(); // random number in range [0, 1)
        let y = rng.gen_range(-10.0..10.0);
        println!("x is: {}", x);
        println!("y is: {}", y);
    }

    println!("Dice roll: {}", rng.gen_range(1..=6));
    println!("Number from 0 to 9: {}", rng.gen_range(0..10));
    
}

// 使用 println! 占位符打印值
fn test_pattern(){
    let x = 5;
    let y = 10;
    println!("x = {}, y = {}", x, y);

}

// #![allow(dead_code)] , 或者加感叹号用于文件头部
// #[allow(dead_code)] // 压制未使用代码的警告， 通过RUSTFLAGS环境变量使用cargo传递它：RUSTFLAGS="$RUSTFLAGS -A dead_code" cargo build
// 禁用此警告的另一种方法是在标识符前面加上_： fn _test_io()
fn test_io() {
    println!("Guess the number!");

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {}", guess);
}

fn test_panics(){
    // let x: Result<u32, &str> = Err("emergency failure");
    // x.unwrap(); // `emergency failure` 的 panics

    let x2: Result<u32, &str> = Err("emergency failure");
    x2.expect("Testing expect"); // `Testing expect: emergency failure` 的 panics
}

fn test_game() {
    println!("Guess the number!");
    let secret_number = thread_rng().gen_range(1..101);
    println!("The secret number is: {}", secret_number);

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        // Rust 允许用一个新值来遮蔽 （shadow） guess 之前的值。这允许我们复用 guess 变量的名字，而不是被迫创建两个不同变量，诸如 guess_str 和 guess 之类。
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {}", guess);
        
        
        // cmp 是对比两个的值，因为guess 是 u8 类型的值，所以应该参考文档：https://rustwiki.org/zh-CN/std/cmp/trait.Ord.html#tymethod.cmp
        let enum_val: Ordering = guess.cmp(&secret_number);
        // match 匹配enum类型的值，参考匹配表达式文档：
        // https://rustwiki.org/zh-CN/reference/expressions/match-expr.html?highlight=match#%E5%8C%B9%E9%85%8Dmatch%E8%A1%A8%E8%BE%BE%E5%BC%8F
        match enum_val {
            Ordering::Less => {
                println!("Too small!")
            },
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }

    }
}